package com.kun.video.ui;

import com.kun.video.AbstractApplication;
import com.kun.video.context.DestroyingBean;
import com.kun.video.context.annotation.Autowired;
import com.kun.video.context.annotation.Component;
import com.kun.video.exception.BizException;
import com.kun.video.thread.ComThreadPool;
import com.kun.video.thread.PrioritizedTask;
import com.kun.video.ui.control.button.ButtonEvent;
import javafx.scene.control.Label;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

/**
 * 事件消息队列服务
 *
 * @author gzc
 */
@Component
public class EventQueue implements DestroyingBean {
    private static final Logger log = LoggerFactory.getLogger(EventQueue.class);
    /**
     * 事件注册表（线程安全）
     */
    private final Map<String, Boolean> eventRegistryMap = new ConcurrentHashMap<>(64);
    @Autowired
    private ComThreadPool comThreadPool;

    /**
     * 默认配置构造器
     */
    public EventQueue() {
    }

    /**
     * 提交事件到消息队列
     *
     * @param event           队列事件实例
     * @param successCallback 成功回调（在UI线程执行）
     * @param failureCallback 失败回调（在UI线程执行）
     * @return CompletableFuture 用于异步结果追踪
     */
    public CompletableFuture<Void> submitEvent(ButtonEvent event,
                                               Runnable successCallback,
                                               Runnable failureCallback) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        String eventId = event.getEventId();
        if (!registerEvent(eventId)) {
            handleImmediateFailure(eventId, future, failureCallback);
            return future;
        }
        submitTask(event,
                () -> handleSuccess(eventId, future, successCallback),
                () -> handleFailure(eventId, future, failureCallback));
        return future;
    }

    /**
     * 提交新任务到执行队列
     *
     * @param event   按钮事件（包含执行逻辑和优先级）
     * @param success 成功回调（在UI线程执行）
     * @param failure 失败回调（在UI线程执行）
     * @return Future对象可用于跟踪任务状态
     */
    public Future<?> submitTask(ButtonEvent event,
                                Runnable success,
                                Runnable failure) {
        // 包装为可优先执行的任务
        PrioritizedTask task = new PrioritizedTask(() -> {
            Label label = new Label(event.getEventId());
            try {
                AbstractApplication.updateRunningProgramList(label);
                // 执行核心逻辑
                event.execute();
                // 执行成功回调
                success.run();
            } catch (Throwable throwable) {
                log.error("任务执行失败:{} - ", event.getEventId(), throwable);
                failure.run();
            } finally {
                AbstractApplication.updateRunningProgramList(label);
            }
            // 设置任务优先级
        }, event.getPriority().getValue());
        return comThreadPool.submit(task);
    }

    /**
     * 注册事件（幂等性检查）
     */
    private boolean registerEvent(String eventId) {
        // 使用字符串驻留保证锁粒度
        synchronized (eventId.intern()) {
            if (eventRegistryMap.containsKey(eventId)) {
                log.warn("事件重复提交: {}", eventId);
                return false;
            }
            eventRegistryMap.put(eventId, true);
            log.debug("事件注册成功: {}", eventId);
            return true;
        }
    }

    /**
     * 处理立即失败情况
     */
    private void handleImmediateFailure(String eventId,
                                        CompletableFuture<Void> future,
                                        Runnable failureCallback) {
        failureCallback.run();
        future.completeExceptionally(new BizException("事件已存在: " + eventId));
        log.warn("事件立即失败: {}", eventId);
    }

    /**
     * 处理成功回调
     */
    private void handleSuccess(String eventId,
                               CompletableFuture<Void> future,
                               Runnable successCallback) {
        successCallback.run();
        future.complete(null);
        cleanupEvent(eventId);
        log.info("事件执行成功: {}", eventId);
    }

    /**
     * 处理失败回调
     */
    private void handleFailure(String eventId,
                               CompletableFuture<Void> future,
                               Runnable failureCallback) {
        failureCallback.run();
        future.completeExceptionally(new BizException("事件执行失败: " + eventId));
        cleanupEvent(eventId);
    }

    /**
     * 清理事件注册记录
     */
    private void cleanupEvent(String eventId) {
        eventRegistryMap.remove(eventId);
        log.debug("事件清理完成: {}", eventId);
    }

    @Override
    public void destroy() {
        log.info("开始关闭事件队列...");
        eventRegistryMap.clear();
        log.info("事件队列已关闭，剩余事件: {}", eventRegistryMap.size());
    }
}
